package com.report.wx;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.zhxu.bs.BeanSearcher;
import cn.zhxu.bs.operator.Equal;
import cn.zhxu.bs.util.MapUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.report.dto.request.WechatPhoneReq;
import com.report.dto.request.WechatReq;
import com.report.dto.response.MemberRes;
import com.report.entity.Member;
import com.report.service.IMemberService;
import com.zmh.framework.enums.ImageTypeEnum;
import com.zmh.framework.exception.ResultException;
import com.zmh.framework.redis.RedisCache;
import com.zmh.framework.util.QrCode;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author summer
 * @date 2024-06-18 15:31
 *
 */
@Configuration
@AllArgsConstructor
@Slf4j
public class WechatService {

    private final WxMpService wxMpService;
    private final RedisCache redisCache;
    private static final String AVATARURL="https://oss.xinyanbao.cn/image/headPortrait.png";

    public  WxMpQrCodeTicket login(Integer type){
        try {
            WxMpQrCodeTicket wxMpQrCodeTicket = wxMpService.getQrcodeService().qrCodeCreateTmpTicket("login_" +  IdUtil.fastSimpleUUID(), 3600);
            String code = QrCode.sendCode(wxMpQrCodeTicket.getUrl(), 400, 400, ImageTypeEnum.PNG);
            redisCache.set("wx:"+wxMpQrCodeTicket.getTicket(),type.toString(),1L, TimeUnit.HOURS);
            wxMpQrCodeTicket.setUrl(code);
            return  wxMpQrCodeTicket;
        } catch (WxErrorException e) {
            throw new ResultException(e.getMessage());
        }
    }


    public String configAccess(String signature, String timestamp, String nonce, String echostr) {
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            log.error("签名校验 ===》 非法请求");
            return null;
        }
        log.error("签名校验 ===》 验证成功");
        return echostr;
    }

    private final WxMpMessageRouter wxMpMessageRouter;



    public String receiver(@RequestBody String xml){
        WxMpXmlMessage wxMpXmlMessage =  WxMpXmlMessage.fromXml(xml);
        try {
            WxMpXmlOutMessage route = wxMpMessageRouter.route(wxMpXmlMessage);
            return route==null?"":route.toXml();
        }catch (Exception e){
            throw new ResultException("微信路由异常错误");
        }
    }

    private final WxMaService wxMaService;

    private final IMemberService memberService;

    private final BeanSearcher beanSearcher;

    public MemberRes getUserPhone(WechatPhoneReq wechatPhoneReq)   {
        try {

            WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(wechatPhoneReq.getCode());
            String openCode = wechatPhoneReq.getOpenIdCode();
            String phoneNumber = phoneNoInfo.getPhoneNumber();
            Map<String, Object> build = MapUtils.builder().field(MemberRes::getPhone, phoneNumber).op(Equal.class).build();
            MemberRes memberRes = beanSearcher.searchFirst(MemberRes.class, build);
            WxMaJscode2SessionResult wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(openCode);
            String unionId = wxMaJscode2SessionResult.getUnionid();
            Map<String, Object> build1 = MapUtils.builder().field(MemberRes::getUnionId, unionId).op(Equal.class).build();
            MemberRes memberRes1 = beanSearcher.searchFirst(MemberRes.class, build1);
            if(ObjectUtil.isEmpty(memberRes) && ObjectUtil.isEmpty(memberRes1) ){
                memberRes=new MemberRes();
                memberRes.setPhone(phoneNumber);
                memberRes.setIdNum(RandomUtil.randomNumbers(5));
                memberRes.setNickName("用户"+RandomUtil.randomString(6));
                memberRes.setMemberState(0);
                memberRes.setRuleId(1);
                memberRes.setMiniOpenId(openCode);
                memberRes.setAvatarUrl(AVATARURL);
                memberRes.setUnionId(unionId);
                memberRes.setMiniOpenId(wxMaJscode2SessionResult.getOpenid());
                memberRes.setUnionId(wxMaJscode2SessionResult.getUnionid());
                memberRes.setLoginTime(LocalDateTime.now());
                memberService.save(Convert.convert(Member.class, memberRes));
            }else if(ObjectUtil.isNotEmpty(memberRes) &&  ObjectUtil.isEmpty(memberRes1) ){
                Member member = memberService.getById(memberRes.getId());
                memberRes.setUnionId(unionId);
                memberRes.setMiniOpenId(openCode);
                member.setMiniOpenId(openCode);
                member.setUnionId(unionId);
                member.setLoginTime(LocalDateTime.now());
                memberService.updateById(member);
            }else if(ObjectUtil.isEmpty(memberRes) &&  ObjectUtil.isNotEmpty(memberRes1) ){
                Member member = memberService.getById(memberRes1.getId());
                member.setMiniOpenId(openCode);
                member.setPhone(phoneNumber);
                member.setLoginTime(LocalDateTime.now());
                memberService.updateById(member);
                return memberService.getByMemberInfo(memberRes1.getId());
            }
            StpUtil.login(memberRes.getId());
            return memberRes;
        }catch (Exception e){
            throw new ResultException(e.getMessage());
        }
    }

    public String getOpenId(WechatReq wechatReq){
        try {
            WxMaJscode2SessionResult wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(wechatReq.getCode());

            return wxMaJscode2SessionResult.getOpenid();
        }catch (Exception e){
            throw new ResultException(e.getMessage());
        }
    }
}
